/**
 * Markdown安全配置工具
 * 提供安全的HTML清理和内容过滤功能
 */

// 允许的HTML标签
const ALLOWED_TAGS = [
  "h1",
  "h2",
  "h3",
  "h4",
  "h5",
  "h6",
  "p",
  "br",
  "hr",
  "strong",
  "b",
  "em",
  "i",
  "u",
  "s",
  "del",
  "ins",
  "ul",
  "ol",
  "li",
  "blockquote",
  "pre",
  "code",
  "a",
  "img",
  "table",
  "thead",
  "tbody",
  "tr",
  "th",
  "td",
  "div",
  "span",
];

// 允许的HTML属性
const ALLOWED_ATTRIBUTES = {
  a: ["href", "title", "target"],
  img: ["src", "alt", "title", "width", "height"],
  code: ["class"],
  pre: ["class"],
  div: ["class"],
  span: ["class"],
  table: ["class"],
  th: ["align"],
  td: ["align"],
};

// 危险的标签和属性
const DANGEROUS_TAGS = [
  "script",
  "iframe",
  "object",
  "embed",
  "form",
  "input",
  "button",
  "link",
  "meta",
  "style",
  "base",
  "applet",
];

const DANGEROUS_ATTRIBUTES = [
  "onclick",
  "onload",
  "onerror",
  "onmouseover",
  "onmouseout",
  "onfocus",
  "onblur",
  "onchange",
  "onsubmit",
  "onreset",
  "javascript:",
  "vbscript:",
  "data:",
  "about:",
];

/**
 * 安全的Markdown配置
 */
export const secureMarkdownConfig = {
  editorConfig: {
    renderDelay: 0,
    toolbarsExclude: ["*"],
  },
  // 启用HTML清理
  sanitize: true,
  // 自定义清理函数
  sanitizeFn: html => {
    return sanitizeHtml(html);
  },
  // 配置语法高亮
  codeHighlightExtensionMap: {
    js: "javascript",
    ts: "typescript",
    py: "python",
    java: "java",
    cpp: "cpp",
    c: "c",
  },
  // 主题配置
  previewTheme: "github",
  codeTheme: "github",
  // 渲染配置
  preview: {
    delay: 0,
    hljs: {
      lineNumber: true,
    },
  },
};

/**
 * HTML内容清理函数
 * @param {string} html - 需要清理的HTML内容
 * @returns {string} - 清理后的安全HTML内容
 */
export function sanitizeHtml(html) {
  if (!html || typeof html !== "string") {
    return "";
  }

  // 创建临时DOM元素进行解析
  const tempDiv = document.createElement("div");
  tempDiv.innerHTML = html;

  // 递归清理所有节点
  cleanNode(tempDiv);

  return tempDiv.innerHTML;
}

/**
 * 递归清理DOM节点
 * @param {Element} node - 需要清理的DOM节点
 */
function cleanNode(node) {
  if (!node || !node.childNodes) {
    return;
  }

  // 转换为数组以避免在遍历时修改集合
  const children = Array.from(node.childNodes);

  children.forEach(child => {
    if (child.nodeType === Node.ELEMENT_NODE) {
      const tagName = child.tagName.toLowerCase();

      // 移除危险标签
      if (DANGEROUS_TAGS.includes(tagName)) {
        child.remove();
        return;
      }

      // 检查是否为允许的标签
      if (!ALLOWED_TAGS.includes(tagName)) {
        // 不允许的标签，但保留其内容
        const parent = child.parentNode;
        while (child.firstChild) {
          parent.insertBefore(child.firstChild, child);
        }
        child.remove();
        return;
      }

      // 清理属性
      cleanAttributes(child);

      // 递归清理子节点
      cleanNode(child);
    } else if (child.nodeType === Node.TEXT_NODE) {
      // 文本节点，检查是否包含危险内容
      const textContent = child.textContent || "";
      if (containsDangerousContent(textContent)) {
        child.textContent = sanitizeText(textContent);
      }
    }
  });
}

/**
 * 清理元素属性
 * @param {Element} element - 需要清理属性的元素
 */
function cleanAttributes(element) {
  const tagName = element.tagName.toLowerCase();
  const allowedAttrs = ALLOWED_ATTRIBUTES[tagName] || [];

  // 获取所有属性名
  const attributes = Array.from(element.attributes);

  attributes.forEach(attr => {
    const attrName = attr.name.toLowerCase();
    const attrValue = attr.value.toLowerCase();

    // 检查是否为危险属性
    const isDangerous = DANGEROUS_ATTRIBUTES.some(
      dangerous => attrName.includes(dangerous) || attrValue.includes(dangerous)
    );

    if (isDangerous || !allowedAttrs.includes(attrName)) {
      element.removeAttribute(attr.name);
    } else {
      // 清理属性值
      element.setAttribute(attr.name, sanitizeAttributeValue(attr.value));
    }
  });
}

/**
 * 检查文本是否包含危险内容
 * @param {string} text - 需要检查的文本
 * @returns {boolean} - 是否包含危险内容
 */
function containsDangerousContent(text) {
  const lowerText = text.toLowerCase();
  return DANGEROUS_ATTRIBUTES.some(dangerous => lowerText.includes(dangerous));
}

/**
 * 清理文本内容
 * @param {string} text - 需要清理的文本
 * @returns {string} - 清理后的文本
 */
function sanitizeText(text) {
  let cleanText = text;

  // 移除危险的协议和脚本
  DANGEROUS_ATTRIBUTES.forEach(dangerous => {
    const regex = new RegExp(dangerous.replace(":", "\\:"), "gi");
    cleanText = cleanText.replace(regex, "");
  });

  return cleanText;
}

/**
 * 清理属性值
 * @param {string} value - 属性值
 * @returns {string} - 清理后的属性值
 */
function sanitizeAttributeValue(value) {
  let cleanValue = value;

  // 移除危险的协议
  const dangerousProtocols = ["javascript:", "vbscript:", "data:", "about:"];
  dangerousProtocols.forEach(protocol => {
    const regex = new RegExp(protocol, "gi");
    cleanValue = cleanValue.replace(regex, "");
  });

  // 对于href属性，只允许http、https和mailto协议
  if (cleanValue.includes("://")) {
    const allowedProtocols = ["http://", "https://", "mailto:"];
    const hasAllowedProtocol = allowedProtocols.some(protocol => cleanValue.toLowerCase().startsWith(protocol));
    if (!hasAllowedProtocol) {
      cleanValue = "#";
    }
  }

  return cleanValue;
}

/**
 * 验证Markdown内容是否安全
 * @param {string} content - Markdown内容
 * @returns {object} - 验证结果
 */
export function validateMarkdownContent(content) {
  const issues = [];

  if (!content || typeof content !== "string") {
    return { isValid: true, issues: [] };
  }

  // 检查是否包含危险标签
  DANGEROUS_TAGS.forEach(tag => {
    const regex = new RegExp(`<${tag}[^>]*>`, "gi");
    if (regex.test(content)) {
      issues.push(`包含危险标签: ${tag}`);
    }
  });

  // 检查是否包含危险属性
  DANGEROUS_ATTRIBUTES.forEach(attr => {
    if (content.toLowerCase().includes(attr)) {
      issues.push(`包含危险属性: ${attr}`);
    }
  });

  return {
    isValid: issues.length === 0,
    issues,
  };
}

/**
 * 开发环境下的内容安全检查
 * @param {string} content - 需要检查的内容
 */
export function devSecurityCheck(content) {
  if (import.meta.env.DEV) {
    const validation = validateMarkdownContent(content);
    if (!validation.isValid) {
      // 开发环境下的安全检查
    }
  }
}
